2013-09-21 01:22:48 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
// Code-hosting website
|
|
|
|
// ````````````````````
|
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
// CONFIGURATION
|
|
|
|
// `````````````
|
|
|
|
|
2013-09-21 01:22:48 +00:00
|
|
|
define('BASEDIR', __DIR__.'\\');
|
2013-09-21 01:52:12 +00:00
|
|
|
define('SITE_TITLE', 'code.ivysaur.me');
|
|
|
|
define('PAGE_THUMB_W', 60);
|
|
|
|
define('PAGE_THUMB_H', 60);
|
2013-09-21 03:10:24 +00:00
|
|
|
define('INDEX_THUMB_W', 90);
|
2013-09-21 07:01:49 +00:00
|
|
|
define('INDEX_THUMB_H', 32); // recommend a multiple of the jpg iDCT block size
|
2013-09-21 01:22:48 +00:00
|
|
|
|
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-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
|
|
|
/**
|
|
|
|
* Remove a directory tree and all its contents.
|
|
|
|
*
|
|
|
|
* @author http://www.php.net/manual/en/function.rmdir.php#110489
|
|
|
|
* @param string $dir
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
function rmdir_recursive($dir) {
|
|
|
|
$files = array_diff(scandir($dir), array('.','..'));
|
|
|
|
foreach ($files as $file) {
|
|
|
|
if (is_dir("$dir/$file")) {
|
|
|
|
rmdir_recursive("$dir/$file");
|
|
|
|
} else {
|
|
|
|
unlink("$dir/$file");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rmdir($dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2013-09-21 04:52:48 +00:00
|
|
|
$base = hesc($sz);
|
|
|
|
$base = preg_replace('~(https?://[^ \\r\\n\\t]+)~i', '<a href="\\1">\\1</a>', $base);
|
2013-09-21 03:10:24 +00:00
|
|
|
|
2013-09-21 04:52:48 +00:00
|
|
|
return nl2br($base);
|
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 = '';
|
2013-09-21 01:22:48 +00:00
|
|
|
private $longdesc = '';
|
|
|
|
private $images = array();
|
|
|
|
private $downloads = array();
|
|
|
|
|
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);
|
|
|
|
foreach($ls as $file) {
|
|
|
|
if ($file[0] == '.') continue;
|
|
|
|
|
|
|
|
if ($file == 'README.txt') {
|
|
|
|
$this->longdesc = file_get_contents($this->dir.'README.txt');
|
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], ' .');
|
|
|
|
}
|
|
|
|
|
2013-09-21 01:22:48 +00:00
|
|
|
$this->shortdesc = array_shift(explode("\n", $this->longdesc));
|
2013-09-21 04:24:52 +00:00
|
|
|
$this->shortdesc[0] = strtolower($this->shortdesc[0]); // cosmetic lowercase
|
2013-09-21 01:22:48 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_image($file)) {
|
|
|
|
$this->images[] = $file;
|
|
|
|
} else {
|
|
|
|
$this->downloads[] = $file;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
if (count($this->images)) {
|
2013-09-21 07:01:49 +00:00
|
|
|
$this->homeimage = mkthumbnail(
|
2013-09-21 03:10:24 +00:00
|
|
|
BASEDIR.'wwwroot/srv/'.$this->projname.'_0.'.str_ext($this->images[0]),
|
2013-09-21 07:01:49 +00:00
|
|
|
null, // raw handle
|
2013-09-21 03:10:24 +00:00
|
|
|
INDEX_THUMB_W, INDEX_THUMB_H
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2013-09-21 01:52:12 +00:00
|
|
|
// Copy downloads to wwwroot
|
|
|
|
|
|
|
|
foreach($this->downloads as $idx => $filename) {
|
|
|
|
copy($this->dir.$filename, BASEDIR.'wwwroot/srv/'.$filename);
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2013-09-21 01:52:12 +00:00
|
|
|
public function index() {
|
2013-09-21 03:10:24 +00:00
|
|
|
?>
|
|
|
|
<h2><a href="index.html"><?=hesc(SITE_TITLE)?></a> > <?=hesc($this->projname)?></h2>
|
|
|
|
|
|
|
|
<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
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
<strong>ABOUT</strong>
|
2013-09-21 01:52:12 +00:00
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
<p><?=text2html($this->longdesc)?></p>
|
|
|
|
|
|
|
|
<?php if (count($this->downloads)) { ?>
|
|
|
|
|
|
|
|
<strong>DOWNLOAD</strong>
|
2013-09-21 01:52:12 +00:00
|
|
|
|
|
|
|
<ul>
|
2013-09-21 03:10:24 +00:00
|
|
|
<?php foreach($this->downloads as $filename) { ?>
|
|
|
|
<li>
|
|
|
|
<a href="srv/<?=hesc(urlencode($filename))?>"><?=hesc($filename)?></a>
|
|
|
|
<small>
|
|
|
|
<?=hesc(fbytes(filesize(BASEDIR.'wwwroot/srv/'.$filename)))?>
|
|
|
|
</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>
|
|
|
|
<?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" >
|
|
|
|
<meta name="viewport" content="width=768px" >
|
|
|
|
<link type="text/css" rel="stylesheet" href="style.css">
|
|
|
|
<title><?=hesc($title)?></title>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div id="container">
|
|
|
|
<div id="content">
|
|
|
|
<?=$content?>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
<?php
|
|
|
|
return ob_get_clean();
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildall() {
|
|
|
|
|
|
|
|
// Clean up webroot
|
|
|
|
|
|
|
|
if (file_exists(BASEDIR.'wwwroot')) {
|
|
|
|
rmdir_recursive(BASEDIR.'wwwroot');
|
|
|
|
}
|
|
|
|
|
|
|
|
echo "Creating directories...\n";
|
2013-09-21 01:22:48 +00:00
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
mkdir(BASEDIR.'wwwroot');
|
|
|
|
mkdir(BASEDIR.'wwwroot/srv');
|
|
|
|
|
|
|
|
// Copy in static files
|
|
|
|
|
|
|
|
foreach(scandir(BASEDIR.'static') as $static) {
|
|
|
|
if ($static[0] == '.' || is_dir($static) /* fixme */) continue;
|
|
|
|
copy(BASEDIR.'static/'.$static, BASEDIR.'wwwroot/'.$static);
|
|
|
|
}
|
2013-09-21 01:52:12 +00:00
|
|
|
|
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;
|
|
|
|
$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];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build all projects
|
|
|
|
|
|
|
|
$plist = array();
|
|
|
|
$count = 0;
|
|
|
|
|
2013-09-21 07:01:49 +00:00
|
|
|
$handles = array();
|
|
|
|
$handle_lookup = array();
|
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
foreach($projects as $dirname => $projectname) {
|
|
|
|
|
|
|
|
echo sprintf("[%2d/%2d] ".$projectname."...", ++$count, count($projects));
|
|
|
|
|
|
|
|
$pr = new CProject($dirname, $projectname);
|
|
|
|
$pr->write();
|
|
|
|
$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;
|
|
|
|
}
|
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
echo " done\n";
|
|
|
|
}
|
|
|
|
|
2013-09-21 07:01:49 +00:00
|
|
|
// Build homepage spritesheet
|
|
|
|
|
|
|
|
mkspritesheet($handles, BASEDIR.'wwwroot/logos.jpg', INDEX_THUMB_W, INDEX_THUMB_H);
|
|
|
|
array_map('imagedestroy', $handles); // free
|
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
// Build index page
|
|
|
|
|
|
|
|
ob_start();
|
|
|
|
?>
|
|
|
|
<h2><?=hesc(SITE_TITLE)?></h2>
|
|
|
|
|
|
|
|
<img src="overview.jpg" class="headimg">
|
|
|
|
|
|
|
|
<p>
|
|
|
|
This page contains several assorted projects, which no longer have any relation. They are listed in roughly chronological order (newest first). <strong>Unless specified otherwise</strong>, you may feel free to use and modify both the binaries and any source code, for any purpose, on the general condition you do not misrepresent who the author is (BSD license).
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Some of these projects formerly appeared on Google Code <a href="https://code.google.com/p/mappy/">here</a>, but were moved following the discontinuation of the Google Code binary download system.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
For bug reports, feature requests, or if you need any help, please
|
|
|
|
<a
|
|
|
|
href="http://www.google.com/recaptcha/mailhide/d?k=01GuAWzMc9JjSdooo-2KCMQA==&c=kgR3dBrP39yhPIy8FvLFbuBLmWqorQBDc_Zjbw6NAmU="
|
|
|
|
onclick="window.open('http://www.google.com/recaptcha/mailhide/d?k\07501GuAWzMc9JjSdooo-2KCMQA\75\75\46c\75kgR3dBrP39yhPIy8FvLFbuBLmWqorQBDc_Zjbw6NAmU\075', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;"
|
|
|
|
title="Reveal this e-mail address"
|
|
|
|
>click here</a> to email me.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<img src="projects.jpg" class="headimg">
|
|
|
|
|
|
|
|
<table class="projtable">
|
|
|
|
<?php foreach ($plist as $pr) { ?>
|
|
|
|
<tr>
|
|
|
|
<td>
|
2013-09-21 07:01:49 +00:00
|
|
|
<a href="<?=hesc(urlencode($pr->projname))?>.html"><?=(is_null($handle_lookup[$pr->projname]) ? '<img src="no_image.png" class="homeimage">' : '<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>
|
|
|
|
<strong><?=hesc($pr->projname)?></strong>,
|
|
|
|
<?=hesc($pr->shortdesc)?>
|
|
|
|
<a href="<?=hesc(urlencode($pr->projname))?>.html">more...</a>
|
2013-09-21 04:52:48 +00:00
|
|
|
<?php if (strlen($pr->subtag)) { ?>
|
|
|
|
<br>
|
|
|
|
<small><?=hesc($pr->subtag)?></small>
|
|
|
|
<?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);
|
|
|
|
|
|
|
|
echo "All processes complete.\n";
|
|
|
|
|
|
|
|
}
|
2013-09-21 01:22:48 +00:00
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
buildall();
|