smaller prog previews + self test
1
www/data/binaries/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.zip
|
@ -230,6 +230,8 @@ body {
|
||||
background-color: #555; }
|
||||
#headerdiv .tabrow .tab_active {
|
||||
background-color: #442222; }
|
||||
#headerdiv .tabrow .tab_admin {
|
||||
background-color: #222244; }
|
||||
#headerdiv .tabrow .tab_split {
|
||||
flex: auto; }
|
||||
#headerdiv .tabrow .tab_github {
|
||||
@ -1051,6 +1053,8 @@ html, body {
|
||||
.keyvaluelist div {
|
||||
display: flex;
|
||||
flex-direction: row; }
|
||||
.keyvaluelist div span {
|
||||
align-self: center; }
|
||||
.keyvaluelist div span:first-child {
|
||||
font-weight: bold;
|
||||
min-width: 500px; }
|
||||
@ -1064,6 +1068,21 @@ html, body {
|
||||
.kvl_300 div span:first-child {
|
||||
min-width: 300px; }
|
||||
|
||||
.consistency_result_ok, .consistency_result_warn, .consistency_result_err {
|
||||
min-width: 400px;
|
||||
border: 1px solid #888;
|
||||
padding: 0 5px;
|
||||
margin: 1px 0; }
|
||||
|
||||
.consistency_result_ok {
|
||||
background: #0F0; }
|
||||
|
||||
.consistency_result_warn {
|
||||
background: #FF0; }
|
||||
|
||||
.consistency_result_err {
|
||||
background: #F00; }
|
||||
|
||||
/* 400px */
|
||||
#loginform div {
|
||||
display: flex;
|
||||
|
6
www/data/css/styles.min.css
vendored
@ -48,6 +48,7 @@ body{background-color:#EEE;color:#CCC;font-family:serif}
|
||||
#headerdiv .tabrow .tab{display:flex;justify-content:center;align-items:center;background-color:#222;color:#CCC;border-left:1px solid #000;border-right:1px solid #000;font-weight:bold;text-decoration:none;margin:0 0 0 20px;padding:2px 5px;min-width:64px;text-align:center;flex:initial}
|
||||
#headerdiv .tabrow .tab:hover{cursor:pointer;background-color:#555}
|
||||
#headerdiv .tabrow .tab_active{background-color:#422}
|
||||
#headerdiv .tabrow .tab_admin{background-color:#224}
|
||||
#headerdiv .tabrow .tab_split{flex:auto}
|
||||
#headerdiv .tabrow .tab_github{background-color:#4078c0;border-left:1px solid #111;border-right:0;color:black}
|
||||
#headerdiv .tabrow .tab_github:hover{background-color:#c9510c;color:black}
|
||||
@ -260,10 +261,15 @@ html,body{margin:0;padding:0;height:100%}
|
||||
.egh_ajaxOutput{display:flex;box-sizing:border-box;width:100%;align-self:center;justify-self:center;margin-left:auto;margin-right:auto;resize:none;height:300px}
|
||||
.keyvaluelist{display:flex;flex-direction:column}
|
||||
.keyvaluelist div{display:flex;flex-direction:row}
|
||||
.keyvaluelist div span{align-self:center}
|
||||
.keyvaluelist div span:first-child{font-weight:bold;min-width:500px}
|
||||
.kvl_100 div span:first-child{min-width:100px}
|
||||
.kvl_200 div span:first-child{min-width:200px}
|
||||
.kvl_300 div span:first-child{min-width:300px}
|
||||
.consistency_result_ok,.consistency_result_warn,.consistency_result_err{min-width:400px;border:1px solid #888;padding:0 5px;margin:1px 0}
|
||||
.consistency_result_ok{background:#0F0}
|
||||
.consistency_result_warn{background:#FF0}
|
||||
.consistency_result_err{background:#F00}
|
||||
#loginform div{display:flex;flex-direction:column}
|
||||
#loginform div button{margin:10px 0;padding:0}
|
||||
.loginerror{display:flex;background:#f44;font-weight:bold;padding:0 5px;margin:5px 0 20px 0}
|
||||
|
@ -29,7 +29,7 @@
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
span {align-self: center;}
|
||||
span:first-child {
|
||||
font-weight: bold;
|
||||
min-width: 500px;
|
||||
@ -45,3 +45,13 @@
|
||||
.kvl_100 div span:first-child { min-width: 100px; }
|
||||
.kvl_200 div span:first-child { min-width: 200px; }
|
||||
.kvl_300 div span:first-child { min-width: 300px; }
|
||||
|
||||
.consistency_result_ok, .consistency_result_warn, .consistency_result_err {
|
||||
min-width: 400px;
|
||||
border: 1px solid #888;
|
||||
padding: 0 5px;
|
||||
margin: 1px 0;
|
||||
}
|
||||
.consistency_result_ok { background: #0F0; }
|
||||
.consistency_result_warn { background: #FF0; }
|
||||
.consistency_result_err { background: #F00; }
|
@ -13,6 +13,7 @@ $COL_COMPLEXHOVER_BRD: black;
|
||||
|
||||
$COL_GITHUB: #4078C0;
|
||||
$COL_HIGHLIGHT_RED: #442222;
|
||||
$COL_HIGHLIGHT_BLUE: #222244;
|
||||
|
||||
$FONT_HEADER: Lato, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
$FONT_CODE: Consolas, Monaco, "Courier New", Menlo, monospace;
|
||||
|
@ -53,6 +53,7 @@
|
||||
}
|
||||
|
||||
.tab_active { background-color: $COL_HIGHLIGHT_RED; }
|
||||
.tab_admin { background-color: $COL_HIGHLIGHT_BLUE; }
|
||||
|
||||
.tab_split {
|
||||
flex: auto;
|
||||
|
4
www/data/dynamic/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*
|
||||
!.gitignore
|
||||
!.gitkeep
|
||||
!.htaccess
|
0
www/data/dynamic/.gitkeep
Normal file
1
www/data/dynamic/.htaccess
Normal file
@ -0,0 +1 @@
|
||||
Deny from all
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 276 KiB After Width: | Height: | Size: 276 KiB |
Before Width: | Height: | Size: 348 KiB After Width: | Height: | Size: 348 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 198 KiB |
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 194 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 262 KiB After Width: | Height: | Size: 262 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 164 KiB |
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
@ -8,7 +8,7 @@
|
||||
<a class="tab <?php if ($HEADER_ACTIVE === 'euler') echo 'tab_active'; ?>" href="/blog/1/Project_Euler_with_Befunge">Project Euler</a>
|
||||
<a class="tab <?php if ($HEADER_ACTIVE === 'blog') echo 'tab_active'; ?>" href="/blog">Blog</a>
|
||||
<a class="tab <?php if ($HEADER_ACTIVE === 'programs') echo 'tab_active'; ?>" href="/programs">Programs</a>
|
||||
<?php if (isLoggedInByCookie()): ?><a class="tab tab_active" href="/admin">Admin</a><?php endif; ?>
|
||||
<?php if (isLoggedInByCookie()): ?><a class="tab tab_admin" href="/admin">Admin</a><?php endif; ?>
|
||||
<a class="tab <?php if ($HEADER_ACTIVE === 'about') echo 'tab_active'; ?>" href="/about">About</a>
|
||||
<div class="tab_split" ></div>
|
||||
<?php if (isLoggedInByCookie()): ?><a class="tab tab_logout" href="/logout">{Logout}</a><?php endif; ?>
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
echo '<a href="' . $prog['url'] . '" class="programs_pnl_entry">' . "\n";
|
||||
echo ' <div class="programs_pnl_img">' . "\n";
|
||||
echo ' <img src="' . $prog['thumbnail_url'] . '" alt="Thumbnail ' . $prog['name'] . ' " />' . "\n";
|
||||
echo ' <img src="' . $prog['preview_url'] . '" alt="Thumbnail ' . $prog['name'] . ' " />' . "\n";
|
||||
echo ' </div>' . "\n";
|
||||
echo ' <div class="programs_pnl_center">' . "\n";
|
||||
echo htmlspecialchars($prog['name']) . "\n";
|
||||
|
@ -37,8 +37,9 @@ $URL_RULES =
|
||||
[ 'url' => ['api', 'statsping'], 'target' => 'pages/api_stats.php', 'options' => [ 'Name' => '%GET%', 'ClientID' => '%GET%', 'Version' => '%GET%', 'ProviderStr' => '%GET%', 'ProviderID' => '%GET%', 'NoteCount' => '%GET%', ], ],
|
||||
|
||||
[ 'url' => ['admin'], 'target' => 'pages/admin.php', 'options' => [ '_opt' => 'password'], ],
|
||||
|
||||
[ 'url' => ['admin', 'cmd', '?{cmd}'], 'target' => 'pages/admin_cmd.php', 'options' => [ '_opt' => 'password', 'cmd' => '%URL%'], ],
|
||||
[ 'url' => ['admin', 'egh', '?{cmd}'], 'target' => 'pages/su_ajax.php', 'options' => [ 'suffix' => 'egh', 'cmd' => '%URL%', 'secret' => '%GET%' ], ],
|
||||
|
||||
[ 'url' => ['su_ajax', '?{cmd}'], 'target' => 'pages/su_ajax.php', 'options' => [ 'suffix' => '', 'cmd' => '%URL%', 'secret' => '%GET%' ], ],
|
||||
[ 'url' => ['su_ajax'], 'target' => 'pages/su_ajax.php', 'options' => [ 'suffix' => '', 'cmd' => '%GET%', 'secret' => '%GET%' ], ],
|
||||
|
||||
@ -85,7 +86,7 @@ try {
|
||||
|
||||
$parse = parse_url($requri);
|
||||
|
||||
$path = strtolower(isset($parse['path']) ? $parse['path'] : '');
|
||||
$path = isset($parse['path']) ? $parse['path'] : '';
|
||||
$pathparts = preg_split('@/@', $path, NULL, PREG_SPLIT_NO_EMPTY);
|
||||
$partcount = count($pathparts);
|
||||
|
||||
@ -187,6 +188,5 @@ try {
|
||||
//TODO better gh widget
|
||||
//TODO remove db table prefixes
|
||||
//TODO euler insert+show 32bit | 64bit mode
|
||||
//TODO optimize image sizes for display/download (? - auto?)
|
||||
//TODO send cache header (?)
|
||||
//TODO global uncached error logger -> send by mail
|
||||
|
@ -182,3 +182,110 @@ function clearLoginCookie()
|
||||
{
|
||||
setcookie("mikescher_auth", "", time()+30);
|
||||
}
|
||||
|
||||
/**
|
||||
* easy image resize function
|
||||
* @author http://www.nimrodstech.com/php-image-resize/
|
||||
* @param $file - file name to resize
|
||||
* @param $string - The image data, as a string
|
||||
* @param $width - new image width
|
||||
* @param $height - new image height
|
||||
* @param $proportional - keep image proportional, default is no
|
||||
* @param $output - name of the new file (include path if needed)
|
||||
* @param $quality - enter 1-100 (100 is best quality) default is 100
|
||||
* @return boolean|resource
|
||||
*/
|
||||
function smart_resize_image($file, $string = null, $width = 0, $height = 0, $proportional = false, $output = 'file', $quality = 100
|
||||
) {
|
||||
|
||||
if ( $height <= 0 && $width <= 0 ) return false;
|
||||
if ( $file === null && $string === null ) return false;
|
||||
|
||||
# Setting defaults and meta
|
||||
$info = $file !== null ? getimagesize($file) : getimagesizefromstring($string);
|
||||
$image = '';
|
||||
$final_width = 0;
|
||||
$final_height = 0;
|
||||
list($width_old, $height_old) = $info;
|
||||
$cropHeight = $cropWidth = 0;
|
||||
|
||||
# Calculating proportionality
|
||||
if ($proportional) {
|
||||
if ($width == 0) $factor = $height/$height_old;
|
||||
elseif ($height == 0) $factor = $width/$width_old;
|
||||
else $factor = min( $width / $width_old, $height / $height_old );
|
||||
|
||||
$final_width = round( $width_old * $factor );
|
||||
$final_height = round( $height_old * $factor );
|
||||
}
|
||||
else {
|
||||
$final_width = ( $width <= 0 ) ? $width_old : $width;
|
||||
$final_height = ( $height <= 0 ) ? $height_old : $height;
|
||||
$widthX = $width_old / $width;
|
||||
$heightX = $height_old / $height;
|
||||
|
||||
$x = min($widthX, $heightX);
|
||||
$cropWidth = ($width_old - $width * $x) / 2;
|
||||
$cropHeight = ($height_old - $height * $x) / 2;
|
||||
}
|
||||
|
||||
# Loading image to memory according to type
|
||||
switch ( $info[2] ) {
|
||||
case IMAGETYPE_JPEG: $file !== null ? $image = imagecreatefromjpeg($file) : $image = imagecreatefromstring($string); break;
|
||||
case IMAGETYPE_GIF: $file !== null ? $image = imagecreatefromgif($file) : $image = imagecreatefromstring($string); break;
|
||||
case IMAGETYPE_PNG: $file !== null ? $image = imagecreatefrompng($file) : $image = imagecreatefromstring($string); break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
|
||||
# This is the resizing/resampling/transparency-preserving magic
|
||||
$image_resized = imagecreatetruecolor( $final_width, $final_height );
|
||||
if ( ($info[2] == IMAGETYPE_GIF) || ($info[2] == IMAGETYPE_PNG) ) {
|
||||
$transparency = imagecolortransparent($image);
|
||||
$palletsize = imagecolorstotal($image);
|
||||
|
||||
if ($transparency >= 0 && $transparency < $palletsize) {
|
||||
$transparent_color = imagecolorsforindex($image, $transparency);
|
||||
$transparency = imagecolorallocate($image_resized, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
|
||||
imagefill($image_resized, 0, 0, $transparency);
|
||||
imagecolortransparent($image_resized, $transparency);
|
||||
}
|
||||
elseif ($info[2] == IMAGETYPE_PNG) {
|
||||
imagealphablending($image_resized, false);
|
||||
$color = imagecolorallocatealpha($image_resized, 0, 0, 0, 127);
|
||||
imagefill($image_resized, 0, 0, $color);
|
||||
imagesavealpha($image_resized, true);
|
||||
}
|
||||
}
|
||||
imagecopyresampled($image_resized, $image, 0, 0, $cropWidth, $cropHeight, $final_width, $final_height, $width_old - 2 * $cropWidth, $height_old - 2 * $cropHeight);
|
||||
|
||||
# Preparing a method of providing result
|
||||
switch ( strtolower($output) ) {
|
||||
case 'browser':
|
||||
$mime = image_type_to_mime_type($info[2]);
|
||||
header("Content-type: $mime");
|
||||
$output = NULL;
|
||||
break;
|
||||
case 'file':
|
||||
$output = $file;
|
||||
break;
|
||||
case 'return':
|
||||
return $image_resized;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
# Writing image according to type to the output destination and image quality
|
||||
switch ( $info[2] ) {
|
||||
case IMAGETYPE_GIF: imagegif($image_resized, $output); break;
|
||||
case IMAGETYPE_JPEG: imagejpeg($image_resized, $output, $quality); break;
|
||||
case IMAGETYPE_PNG:
|
||||
$quality = 9 - (int)((0.9*$quality)/10.0);
|
||||
imagepng($image_resized, $output, $quality);
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -18,6 +18,8 @@ class Blog
|
||||
|
||||
$d['canonical'] = "https://www.mikescher.com" . $d['url'];
|
||||
|
||||
$d['file_fragment'] = __DIR__ . '/../statics/blog/' . $d['fragment'];
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
@ -38,7 +40,40 @@ class Blog
|
||||
|
||||
public static function getPostFragment($post)
|
||||
{
|
||||
return file_get_contents( __DIR__ . '/../statics/blog/' . $post['fragment']);
|
||||
return file_get_contents($post['file_fragment']);
|
||||
}
|
||||
|
||||
public static function checkConsistency()
|
||||
{
|
||||
$keys = [];
|
||||
|
||||
foreach (self::listAll() as $post)
|
||||
{
|
||||
if (in_array($post['id'], $keys)) return ['result'=>'err', 'message' => 'Duplicate key ' . $post['id']];
|
||||
$keys []= $post['id'];
|
||||
|
||||
if ($post['cat'] !== 'log' && $post['cat'] !== 'blog') return ['result'=>'err', 'message' => 'Unknown cat ' . $post['cat']];
|
||||
|
||||
if ($post['type'] === 'markdown') {
|
||||
|
||||
if (!file_exists($post['file_fragment'])) return ['result'=>'err', 'message' => 'Fragment not found ' . $post['fragment']];
|
||||
|
||||
} else if ($post['type'] === 'plain') {
|
||||
|
||||
if (!file_exists($post['file_fragment'])) return ['result'=>'err', 'message' => 'Fragment not found ' . $post['fragment']];
|
||||
|
||||
} else if ($post['type'] === 'euler') {
|
||||
|
||||
// aok
|
||||
|
||||
} else {
|
||||
|
||||
return ['result'=>'err', 'message' => 'Unknown type ' . $post['type']];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return ['result'=>'ok', 'message' => ''];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,5 +67,29 @@ class Euler
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
public static function checkConsistency()
|
||||
{
|
||||
$warn = null;
|
||||
|
||||
$numbers = [];
|
||||
$realname = [];
|
||||
|
||||
foreach (self::listAll() as $ep)
|
||||
{
|
||||
if (in_array($ep['number'], $numbers)) return ['result'=>'err', 'message' => 'Duplicate number ' . $ep['number']];
|
||||
$numbers []= $ep['number'];
|
||||
|
||||
if (in_array($ep['title'], $realname)) return ['result'=>'err', 'message' => 'Duplicate title ' . $ep['title']];
|
||||
$realname []= $ep['title'];
|
||||
|
||||
if (!file_exists($ep['file_description'])) return ['result'=>'err', 'message' => 'file_description not found ' . $ep['file_description']];
|
||||
if (!file_exists($ep['file_code'])) return ['result'=>'err', 'message' => 'file_code not found ' . $ep['file_code']];
|
||||
if (!file_exists($ep['file_explanation'])) return ['result'=>'err', 'message' => 'file_explanation not found ' . $ep['file_explanation']];
|
||||
}
|
||||
|
||||
if ($warn != null) return $warn;
|
||||
return ['result'=>'ok', 'message' => ''];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,4 +26,26 @@ class MikescherGitGraph
|
||||
|
||||
return $v;
|
||||
}
|
||||
|
||||
public static function getPathRenderedData()
|
||||
{
|
||||
return __DIR__ . '/../dynamic/egh.html';
|
||||
}
|
||||
|
||||
public static function includeRender()
|
||||
{
|
||||
if (file_exists(__DIR__ . '/../dynamic/egh.html'))
|
||||
include __DIR__ . '/../dynamic/egh.html';
|
||||
}
|
||||
|
||||
public static function checkConsistency()
|
||||
{
|
||||
$p = self::getPathRenderedData();
|
||||
|
||||
if (!file($p)) return ['result'=>'err', 'message' => 'Rendered data not found'];
|
||||
|
||||
if (filemtime($p) < time()-(3*7*24*60*60)) return ['result'=>'warn', 'message' => 'Rendered data is older than 3 weeks'];
|
||||
|
||||
return ['result'=>'ok', 'message' => ''];
|
||||
}
|
||||
}
|
@ -1,7 +1,11 @@
|
||||
<?php if(count(get_included_files()) ==1) exit("Direct access not permitted.");
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
class Programs
|
||||
{
|
||||
const PROG_LANGS = [ 'Java', 'C#', 'Delphi', 'PHP', 'C++' ];
|
||||
|
||||
const URL_ORDER =
|
||||
[
|
||||
'github',
|
||||
@ -29,8 +33,14 @@ class Programs
|
||||
|
||||
public static function readSingle($a)
|
||||
{
|
||||
$a['thumbnail_url'] = '/data/images/program_thumbnails/' . $a['internal_name'] . '.png';
|
||||
$a['mainimage_url'] = '/data/images/program_img/' . $a['internal_name'] . '.png';
|
||||
$a['mainimage_path'] = __DIR__ . '/../data/images/program_img/' . $a['internal_name'] . '.png';
|
||||
|
||||
$a['preview_url'] = '/data/dynamic/progprev_' . $a['internal_name'] . '.png';
|
||||
$a['preview_path'] = __DIR__ . '/../data/dynamic/progprev_' . $a['internal_name'] . '.png';
|
||||
|
||||
$a['file_longdescription'] = (__DIR__ . '/../statics/programs/' . $a['internal_name'] . '_description.md');
|
||||
|
||||
$a['url'] = '/programs/view/' . $a['internal_name'];
|
||||
|
||||
return $a;
|
||||
@ -73,6 +83,12 @@ class Programs
|
||||
|
||||
public static function urlComparator($a, $b)
|
||||
{
|
||||
$na = 0;
|
||||
$nb = 0;
|
||||
|
||||
if (strpos($a, '#') !== FALSE) { $na = intval(explode('#', $a)[1]); $a=explode('#', $a)[0]; }
|
||||
if (strpos($b, '#') !== FALSE) { $nb = intval(explode('#', $b)[1]); $b=explode('#', $b)[0]; }
|
||||
|
||||
$ia = array_search($a, Programs::URL_ORDER);
|
||||
$ib = array_search($b, Programs::URL_ORDER);
|
||||
|
||||
@ -80,18 +96,153 @@ class Programs
|
||||
if ($ia === false && $ib !== false) return +1; // sort [IA | IB]
|
||||
if ($ia !== false && $ib === false) return -1; // sort [IB | IA]
|
||||
|
||||
if ($ia === $ib) return ($na < $nb) ? -1 : +1;
|
||||
|
||||
return ($ia < $ib) ? -1 : +1;
|
||||
|
||||
}
|
||||
|
||||
public static function sortUrls($urls)
|
||||
public static function getURLs($prog)
|
||||
{
|
||||
$urls = $prog['urls'];
|
||||
uksort($urls, 'self::urlComparator');
|
||||
return $urls;
|
||||
|
||||
$result = [];
|
||||
foreach ($urls as $fulltype => $urldata)
|
||||
{
|
||||
$type = $fulltype;
|
||||
if (strpos($fulltype, '#') !== FALSE) $type=explode('#', $fulltype)[0];
|
||||
|
||||
$caption = '?';
|
||||
$css = '?';
|
||||
$svg = '?';
|
||||
$direct = false;
|
||||
|
||||
if ($type === 'download') { $caption = 'Download'; $css = 'prgv_dl_download'; $svg = 'download'; }
|
||||
if ($type === 'github') { $caption = 'Github'; $css = 'prgv_dl_github'; $svg = 'github'; }
|
||||
if ($type === 'homepage') { $caption = 'Homepage'; $css = 'prgv_dl_homepage'; $svg = 'home'; }
|
||||
if ($type === 'wiki') { $caption = 'Wiki'; $css = 'prgv_dl_wiki'; $svg = 'wiki'; }
|
||||
if ($type === 'playstore') { $caption = 'Google Playstore'; $css = 'prgv_dl_playstore'; $svg = 'playstore'; }
|
||||
if ($type === 'amazonappstore') { $caption = 'Amazon Appstore'; $css = 'prgv_dl_amznstore'; $svg = 'amazon'; }
|
||||
if ($type === 'windowsstore') { $caption = 'Microsoft Store'; $css = 'prgv_dl_winstore'; $svg = 'windows'; }
|
||||
if ($type === 'itunesstore') { $caption = 'App Store'; $css = 'prgv_dl_appstore'; $svg = 'apple'; }
|
||||
if ($type === 'sourceforge') { $caption = 'Sourceforge'; $css = 'prgv_dl_sourceforge'; $svg = 'sourceforge'; }
|
||||
if ($type === 'alternativeto') { $caption = 'AlternativeTo'; $css = 'prgv_dl_alternativeto'; $svg = 'alternativeto'; }
|
||||
|
||||
if (is_array($urldata))
|
||||
{
|
||||
$url = $urldata['url'];
|
||||
if (isset($urldata['caption'])) $caption = $urldata['caption'];
|
||||
if (isset($urldata['css'])) $css = $urldata['css'];
|
||||
if (isset($urldata['svg'])) $svg = $urldata['svg'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$url = $urldata;
|
||||
}
|
||||
|
||||
if ($url === 'direct')
|
||||
{
|
||||
$direct = true;
|
||||
$url = Programs::getDirectDownloadURL($prog);
|
||||
}
|
||||
|
||||
$result []=
|
||||
[
|
||||
'type' => $type,
|
||||
'caption' => $caption,
|
||||
'svg' => $svg,
|
||||
'href' => $url,
|
||||
'css' => $css,
|
||||
'isdirect' => $direct,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function getLicenseUrl($license)
|
||||
{
|
||||
return self::LICENSES[$license];
|
||||
}
|
||||
|
||||
public static function getDirectDownloadURL($prog)
|
||||
{
|
||||
return '/data/binaries/'.$prog['internal_name'].'.zip';
|
||||
}
|
||||
|
||||
public static function getDirectDownloadPath($prog)
|
||||
{
|
||||
return (__DIR__ . '/../data/binaries/'.$prog['internal_name'].'.zip');
|
||||
}
|
||||
|
||||
public static function checkConsistency()
|
||||
{
|
||||
$warn = null;
|
||||
|
||||
$intname = [];
|
||||
$realname = [];
|
||||
|
||||
foreach (self::listAll() as $prog)
|
||||
{
|
||||
if (in_array($prog['internal_name'], $intname)) return ['result'=>'err', 'message' => 'Duplicate internal_name ' . $prog['name']];
|
||||
$intname []= $prog['internal_name'];
|
||||
|
||||
if ($prog['internal_name_alt'] !== null)
|
||||
{
|
||||
if (in_array($prog['internal_name_alt'], $intname)) return ['result'=>'err', 'message' => 'Duplicate internal_name ' . $prog['name']];
|
||||
$intname []= $prog['internal_name_alt'];
|
||||
}
|
||||
|
||||
if (in_array($prog['name'], $realname)) return ['result'=>'err', 'message' => 'Duplicate name ' . $prog['name']];
|
||||
$realname []= $prog['name'];
|
||||
|
||||
if (strpos($prog['internal_name'], ' ') !== FALSE) return ['result'=>'err', 'message' => 'Internal name contains spaces ' . $prog['name']];
|
||||
|
||||
foreach (explode('|', $prog['ui_language']) as $lang) if (convertLanguageToFlag($lang) === null) return ['result'=>'err', 'message' => 'Unknown ui-lang ' . $prog['name']];;
|
||||
|
||||
if (!in_array($prog['prog_language'], self::PROG_LANGS)) return ['result'=>'err', 'message' => 'Unknown prog-lang ' . $prog['name']];
|
||||
|
||||
if (strlen($prog['short_description'])> 128) $warn = ['result'=>'warn', 'message' => 'short_description too long ' . $prog['name']];
|
||||
|
||||
if ($prog['license'] !== null && !array_key_exists($prog['license'], self::LICENSES)) return ['result'=>'err', 'message' => 'Unknown license ' . $prog['name']];
|
||||
|
||||
$isdl = false;
|
||||
foreach (self::getURLs($prog) as $xurl)
|
||||
{
|
||||
if (!in_array($xurl['type'], self::URL_ORDER)) return ['result'=>'err', 'message' => 'Unknown url ' . $xurl['type']];
|
||||
|
||||
if ($xurl['type']==='download' && $xurl['isdirect'] && !file_exists(self::getDirectDownloadPath($prog))) return ['result'=>'err', 'message' => 'Direct download not found ' . $prog['name']];
|
||||
|
||||
if ($xurl['type']==='download' || $xurl['type']==='playstore' || $xurl['type']==='itunesstore') $isdl = true;
|
||||
}
|
||||
|
||||
if (!$isdl) return ['result'=>'err', 'message' => 'No download link ' . $prog['name']];
|
||||
|
||||
if (!file_exists($prog['mainimage_path'])) return ['result'=>'err', 'message' => 'Image not found ' . $prog['name']];
|
||||
|
||||
if (!file_exists($prog['file_longdescription'])) return ['result'=>'err', 'message' => 'Description not found ' . $prog['name']];
|
||||
}
|
||||
|
||||
if ($warn != null) return $warn;
|
||||
return ['result'=>'ok', 'message' => ''];
|
||||
}
|
||||
|
||||
public static function checkThumbnails()
|
||||
{
|
||||
foreach (self::listAll() as $prog)
|
||||
{
|
||||
if (!file_exists($prog['preview_path'])) return ['result'=>'err', 'message' => 'Preview not found ' . $prog['name']];
|
||||
}
|
||||
|
||||
return ['result'=>'ok', 'message' => ''];
|
||||
}
|
||||
|
||||
public static function createPreview($prog)
|
||||
{
|
||||
$src = $prog['mainimage_path'];
|
||||
$dst = $prog['preview_path'];
|
||||
|
||||
smart_resize_image($src , null, 250, 0, true, $dst, 100);
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
<html lang="en">
|
||||
<?php
|
||||
require_once (__DIR__ . '/../internals/base.php');
|
||||
require_once (__DIR__ . '/../internals/mikeschergitgraph.php');
|
||||
global $OPTIONS;
|
||||
?>
|
||||
<head>
|
||||
@ -46,7 +47,7 @@ global $OPTIONS;
|
||||
|
||||
<div class="bc_data about_egh_container">
|
||||
|
||||
<?php if (file_exists(__DIR__ . '/../dynamic/egh.html')) include __DIR__ . '/../dynamic/egh.html' ?>
|
||||
<?php MikescherGitGraph::includeRender(); ?>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -4,13 +4,33 @@
|
||||
require_once (__DIR__ . '/../internals/base.php');
|
||||
require_once (__DIR__ . '/../internals/highscores.php');
|
||||
require_once (__DIR__ . '/../internals/alephnoteStatistics.php');
|
||||
require_once (__DIR__ . '/../internals/blog.php');
|
||||
require_once (__DIR__ . '/../internals/euler.php');
|
||||
require_once (__DIR__ . '/../internals/highscores.php');
|
||||
require_once (__DIR__ . '/../internals/mikeschergitgraph.php');
|
||||
require_once (__DIR__ . '/../internals/programs.php');
|
||||
|
||||
Database::connect();
|
||||
|
||||
$consistency_blog = Blog::checkConsistency();
|
||||
$consistency_prog = Programs::checkConsistency();
|
||||
$consistency_euler = Euler::checkConsistency();
|
||||
$consistency_egh = MikescherGitGraph::checkConsistency();
|
||||
$consistency_progimg = Programs::checkThumbnails();
|
||||
|
||||
?>
|
||||
<?php
|
||||
|
||||
function dumpConsistency($c) {
|
||||
if ($c['result']==='ok') echo "<span class='consistency_result_ok'>OK</span>";
|
||||
else if ($c['result']==='warn') echo "<span class='consistency_result_warn'>".$c['message']."</span>";
|
||||
else echo "<span class='consistency_result_err'>".$c['message']."</span>";
|
||||
}
|
||||
|
||||
?>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Mikescher.com - About</title>
|
||||
<title>Mikescher.com - Admin</title>
|
||||
<link rel="icon" type="image/png" href="/data/images/favicon.png"/>
|
||||
<link rel="canonical" href="https://www.mikescher.com/about"/>
|
||||
<?php printCSS(); ?>
|
||||
@ -39,7 +59,27 @@ Database::connect();
|
||||
<div><span>Date:</span> <span><?php echo exec('git log -1 --format=%cd'); ?></span></div>
|
||||
<div><span>Message:</span><span><?php echo nl2br(trim(exec('git log -1'))); ?></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!------------------------------------------>
|
||||
|
||||
<div class="boxedcontent">
|
||||
<div class="bc_header">Self test</div>
|
||||
|
||||
<div class="bc_data">
|
||||
<div class="keyvaluelist kvl_200">
|
||||
<div><span>Program thumbnails:</span> <?php dumpConsistency($consistency_progimg); ?></div>
|
||||
<div><span>ExtendedGitGraph:</span> <?php dumpConsistency($consistency_egh); ?></div>
|
||||
<div><span>Book thumbnails:</span> <span>?</span></div>
|
||||
<div><span>Blog data:</span> <?php dumpConsistency($consistency_blog); ?></div>
|
||||
<div><span>Euler data:</span> <?php dumpConsistency($consistency_euler); ?></div>
|
||||
<div><span>Programs data:</span> <?php dumpConsistency($consistency_prog); ?></div>
|
||||
</div>
|
||||
<br/>
|
||||
<a class="button" href="/admin/cmd/createProgramThumbnails">Update Program Thumbnails</a>
|
||||
<a class="button" href="/admin/cmd/createBookThumbnails">Update Book Thumbnails</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!------------------------------------------>
|
||||
|
43
www/pages/admin_cmd.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
global $OPTIONS;
|
||||
|
||||
require_once (__DIR__ . '/../internals/base.php');
|
||||
require_once (__DIR__ . '/../internals/programs.php');
|
||||
|
||||
$cmd = $OPTIONS['cmd'];
|
||||
|
||||
if ($cmd === 'createProgramThumbnails')
|
||||
{
|
||||
echo '<!DOCTYPE html>';
|
||||
echo '<html lang="en">';
|
||||
echo '<head>';
|
||||
echo '<meta charset="utf-8">';
|
||||
echo '<title>Mikescher.com - AdminExec</title>';
|
||||
echo '<link rel="icon" type="image/png" href="/data/images/favicon.png"/>';
|
||||
echo '<link rel="canonical" href="https://www.mikescher.com/logout"/>';
|
||||
echo '<meta http-equiv="refresh" content="3; url=/admin; ?>" />';
|
||||
echo '</head>';
|
||||
echo '<body>';
|
||||
|
||||
foreach (Programs::listAll() as $prog)
|
||||
{
|
||||
echo 'Create preview for ' . $prog['name'] . '<br/>' . "\n";
|
||||
Programs::createPreview($prog);
|
||||
}
|
||||
echo 'Finished.' . '<br/>' . "\n";
|
||||
|
||||
echo '<script>setTimeout(function () { window.location.href = "/admin"; }, 3000);</script>';
|
||||
echo '</body>';
|
||||
echo '</html>';
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($cmd === 'createBookThumbnails')
|
||||
{
|
||||
//TODO
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
die('Wrong command.');
|
@ -38,7 +38,7 @@ $allprograms = Programs::listAllNewestFirst($filter);
|
||||
|
||||
echo '<a class="prgl_elem" href="'.$prog['url'].'">';
|
||||
echo ' <div class="prgl_elem_left">';
|
||||
echo ' <img src="' . $prog['thumbnail_url'] . '" alt="Thumbnail ' . $prog['name'] . '" />';
|
||||
echo ' <img src="' . $prog['preview_url'] . '" alt="Thumbnail ' . $prog['name'] . '" />';
|
||||
echo ' </div>';
|
||||
echo ' <div class="prgl_elem_right">';
|
||||
echo ' <div class="prgl_elem_title">' . htmlspecialchars($prog['name']) . '</div>';
|
||||
|
@ -34,7 +34,7 @@ if ($prog === NULL) httpError(404, 'Program not found');
|
||||
<div class="contentheader" id="prgv_header"><h1><?php echo htmlspecialchars($prog['name']); ?></h1><hr/></div>
|
||||
|
||||
<div class="prgv_top">
|
||||
<div class="prgv_left"><img src="<?php echo $prog['thumbnail_url']; ?>" alt="Thumbnail (<?php echo $prog['name'] ?>)" /></div>
|
||||
<div class="prgv_left"><img src="<?php echo $prog['mainimage_url']; ?>" alt="Thumbnail (<?php echo $prog['name'] ?>)" /></div>
|
||||
<div class="prgv_right">
|
||||
<div class="prgv_right_key" style="grid-row:1">Name:</div>
|
||||
<div class="prgv_right_value" style="grid-row:1"><a href="<?php echo $prog['url']; ?>"><?php echo htmlspecialchars($prog['name']) ?></a></div>
|
||||
@ -55,20 +55,14 @@ if ($prog === NULL) httpError(404, 'Program not found');
|
||||
|
||||
<div class="prgv_right_comb" style="grid-row:6">
|
||||
<?php
|
||||
foreach (Programs::sortUrls($prog['urls']) as $type => $url)
|
||||
foreach (Programs::getURLs($prog) as $xurl)
|
||||
{
|
||||
if ($type === 'download' && $url === 'direkt') $url = '/data/binaries/'.$prog['internal_name'].'.zip';
|
||||
|
||||
if ($type === 'download') echo '<a class="iconbutton prgv_dl_download" href="'.$url.'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download" /></svg><span>Download</span></a>';
|
||||
if ($type === 'github') echo '<a class="iconbutton prgv_dl_github" href="'.$url.'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#github" /></svg><span>Github</span></a>';
|
||||
if ($type === 'homepage') echo '<a class="iconbutton prgv_dl_homepage" href="'.$url.'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#home" /></svg><span>Homepage</span></a>';
|
||||
if ($type === 'wiki') echo '<a class="iconbutton prgv_dl_wiki" href="'.$url.'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#wiki" /></svg><span>Wiki</span></a>';
|
||||
if ($type === 'playstore') echo '<a class="iconbutton prgv_dl_playstore" href="'.$url.'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#playstore" /></svg><span>Google Playstore</span></a>';
|
||||
if ($type === 'amazonappstore') echo '<a class="iconbutton prgv_dl_amznstore" href="'.$url.'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#amazon" /></svg><span>Amazon Appstore</span></a>';
|
||||
if ($type === 'windowsstore') echo '<a class="iconbutton prgv_dl_winstore" href="'.$url.'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#windows" /></svg><span>Microsoft Store</span></a>';
|
||||
if ($type === 'itunesstore') echo '<a class="iconbutton prgv_dl_appstore" href="'.$url.'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#apple" /></svg><span>App Store</span></a>';
|
||||
if ($type === 'sourceforge') echo '<a class="iconbutton prgv_dl_sourceforge" href="'.$url.'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#sourceforge" /></svg><span>Sourceforge</span></a>';
|
||||
if ($type === 'alternativeto') echo '<a class="iconbutton prgv_dl_alternativeto" href="'.$url.'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#alternativeto"/></svg><span>AlternativeTo</span></a>';
|
||||
echo '<a class="iconbutton '.$xurl['css'].'" href="'.$xurl['href'].'">';
|
||||
echo '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">';
|
||||
echo '<use xlink:href="/data/images/icons.svg#'.$xurl['svg'].'"/>';
|
||||
echo '</svg>';
|
||||
echo '<span>'.$xurl['caption'].'</span>';
|
||||
echo '</a>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
@ -15,7 +15,7 @@ return
|
||||
'license' => 'GPL-3.0',
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'https://github.com/Mikescher/AbsCanvas/releases',
|
||||
'github' => 'https://github.com/Mikescher/AbsCanvas',
|
||||
],
|
||||
],
|
||||
@ -34,7 +34,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -52,7 +52,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -72,6 +72,12 @@ return
|
||||
[
|
||||
'github' => 'https://github.com/Mikescher/BefunUtils',
|
||||
'wiki' => 'https://github.com/Mikescher/BefunUtils/wiki',
|
||||
'download#1' => ['caption'=>'BefunExec', 'url'=>'https://ci.appveyor.com/project/Mikescher/BefunExec/build/artifacts' ],
|
||||
'download#2' => ['caption'=>'BefunGen', 'url'=>'https://ci.appveyor.com/project/Mikescher/BefunGen/build/artifacts' ],
|
||||
'download#3' => ['caption'=>'BefunWrite', 'url'=>'https://ci.appveyor.com/project/Mikescher/BefunWrite/build/artifacts'],
|
||||
'download#4' => ['caption'=>'BefunRep', 'url'=>'https://ci.appveyor.com/project/Mikescher/BefunRep/build/artifacts' ],
|
||||
'download#5' => ['caption'=>'BefunRun', 'url'=>'https://ci.appveyor.com/project/Mikescher/BefunRun/build/artifacts' ],
|
||||
'download#6' => ['caption'=>'BefunDebug', 'url'=>'https://ci.appveyor.com/project/Mikescher/BefunDebug/build/artifacts'],
|
||||
],
|
||||
],
|
||||
|
||||
@ -89,7 +95,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -107,7 +113,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
'homepage' => 'http://borderlinedefense.99k.org/',
|
||||
],
|
||||
],
|
||||
@ -126,7 +132,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -144,7 +150,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -162,7 +168,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -198,7 +204,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -216,7 +222,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -253,7 +259,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -271,7 +277,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
'sourceforge' => 'http://sourceforge.net/projects/jcircuits/',
|
||||
],
|
||||
],
|
||||
@ -329,7 +335,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
//TODO url
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -347,7 +353,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -365,7 +371,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -383,7 +389,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -420,7 +426,7 @@ return
|
||||
'license' => 'Unlicense',
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'https://github.com/Mikescher/Serpilicum/releases',
|
||||
'github' => 'https://github.com/Mikescher/Serpilicum',
|
||||
],
|
||||
],
|
||||
@ -440,6 +446,7 @@ return
|
||||
'urls' =>
|
||||
[
|
||||
'github' => 'https://github.com/Mikescher/SharkSim',
|
||||
'download' => 'https://github.com/Mikescher/SharkSim/releases',
|
||||
],
|
||||
],
|
||||
|
||||
@ -457,7 +464,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -475,7 +482,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -493,7 +500,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'https://github.com/Mikescher/SuperBitBros/releases',
|
||||
'github' => 'https://github.com/Mikescher/SuperBitBros',
|
||||
],
|
||||
],
|
||||
@ -512,7 +519,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
@ -530,7 +537,7 @@ return
|
||||
'license' => null,
|
||||
'urls' =>
|
||||
[
|
||||
'download' => 'direkt',
|
||||
'download' => 'direct',
|
||||
],
|
||||
],
|
||||
|
||||
|