From acef7d1df8171e2a9ba01ca27659b708b6b39330 Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Wed, 20 Nov 2024 14:59:01 +0000 Subject: [PATCH 01/10] Update donors list. --- html/donors.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/html/donors.php b/html/donors.php index bacdd8a..c6ca6e0 100644 --- a/html/donors.php +++ b/html/donors.php @@ -13,6 +13,9 @@
+ + + From 810c0b2b77ecedc7282d60b353b2404f5d0f1522 Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Fri, 29 Nov 2024 02:58:58 +0000 Subject: [PATCH 02/10] Update donors list. --- html/donors.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/html/donors.php b/html/donors.php index c6ca6e0..2c86359 100644 --- a/html/donors.php +++ b/html/donors.php @@ -13,6 +13,9 @@
20th November 2024M W Magee
19th August 2024Randall Robinson
+ + + From f229f526f74b6705d57a56a2286dd6b893552720 Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Wed, 4 Dec 2024 14:40:21 +0000 Subject: [PATCH 03/10] Update donors list. --- html/donors.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/html/donors.php b/html/donors.php index 2c86359..c1fb3c7 100644 --- a/html/donors.php +++ b/html/donors.php @@ -13,6 +13,9 @@
29th November 2024Kirby Foster
20th November 2024M W Magee
+ + + From 1a4c8faaa1a86ad52c7643ad9f41202936a3cfcd Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Sun, 12 Jan 2025 13:43:37 +0000 Subject: [PATCH 04/10] Update donors list. --- html/donors.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/html/donors.php b/html/donors.php index c1fb3c7..d7f9a6b 100644 --- a/html/donors.php +++ b/html/donors.php @@ -13,6 +13,9 @@
4th December 2024Syed Sajjad Rizvi
29th November 2024Kirby Foster
+ + + From 4649d5b54631af847bb3c71e9e702ead68cfbe57 Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Mon, 6 Oct 2025 17:57:29 +0100 Subject: [PATCH 05/10] Update search results. --- cgi-bin/searchapi.cgi | 3 ++- html/search.shtml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cgi-bin/searchapi.cgi b/cgi-bin/searchapi.cgi index 52e13fc..0e1957d 100755 --- a/cgi-bin/searchapi.cgi +++ b/cgi-bin/searchapi.cgi @@ -1,7 +1,8 @@ #!/bin/bash # Configuration. -STORAGE_PREFIX="/storage/md0" +#STORAGE_PREFIX="/storage/md0" +STORAGE_PREFIX="/data/mirrors" LOCATE_DB="/tmp/mirrors.db" DEF_RESULTS=500 MAX_RESULTS=3000 diff --git a/html/search.shtml b/html/search.shtml index 9c58d5a..3a2ea77 100644 --- a/html/search.shtml +++ b/html/search.shtml @@ -84,7 +84,7 @@ $type = strtok ($result_line, " "); $entry = strtok ("\0"); if ($type == "f" || $type == "l" || $type == "o") { - print ('• ' . $entry . '
'); + print ('• ' . $entry . ' (Visit containing directory)
'); $count++; } elseif ($type == "d") { print ('• ' . $entry . ' (Repeat search in this directory)
'); From 9a745b76324e5340aa2a5038ff20e8972865637d Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Mon, 6 Oct 2025 18:00:15 +0100 Subject: [PATCH 06/10] Update CSS. --- html/dark.css | 15 +++++++++++++++ html/light.css | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/html/dark.css b/html/dark.css index 77491a9..13c1059 100644 --- a/html/dark.css +++ b/html/dark.css @@ -1,3 +1,5 @@ +/* HTML elements */ + a:link { color: #4255ff; text-decoration: none; @@ -16,6 +18,10 @@ body { background-color: #000000; background-image: url("/html/circuit-dark.png"); color: #aeaeae; + margin-bottom: 0; + margin-left: 0; + margin-right: 0; + margin-top: 0; padding-top: 15px; } @@ -60,6 +66,8 @@ td { } +/* Classes */ + .bold { font-weight: bold; } @@ -85,6 +93,10 @@ td { margin-right: 100px; } +.centre { + text-align: center; +} + .heading { font-size: 200%; } @@ -142,6 +154,8 @@ td { } +/* IDs */ + #breadcrumbs { align-self: end; display: flex; @@ -184,6 +198,7 @@ td { justify-content: center; margin-bottom: 10px; margin-top: 20px; + text-align: center; } #footer { diff --git a/html/light.css b/html/light.css index f535e5a..d1a7300 100644 --- a/html/light.css +++ b/html/light.css @@ -1,3 +1,5 @@ +/* HTML elements */ + a:link { color: #2c199c; text-decoration: none; @@ -16,6 +18,10 @@ body { background-color: #ffffff; background-image: url("/html/circuit-light.png"); color: #000000; + margin-bottom: 0; + margin-left: 0; + margin-right: 0; + margin-top: 0; padding-top: 15px; } @@ -60,6 +66,8 @@ td { } +/* Classes */ + .bold { font-weight: bold; } @@ -85,6 +93,10 @@ td { margin-right: 100px; } +.centre { + text-align: center; +} + .heading { font-size: 200%; } @@ -142,6 +154,8 @@ td { } +/* IDs */ + #breadcrumbs { align-self: end; display: flex; @@ -184,6 +198,7 @@ td { justify-content: center; margin-bottom: 10px; margin-top: 20px; + text-align: center; } #footer { From 91b5308ac050016c21236a4b62f74e4333b0a825 Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Mon, 6 Oct 2025 18:02:22 +0100 Subject: [PATCH 07/10] Add support for MarkDown README.md files. --- html/header.php | 1 + html/includes/Parsedown.php | 1712 +++++++++++++++++++++++++++++ html/includes/readme-markdown.php | 14 + 3 files changed, 1727 insertions(+) create mode 100644 html/includes/Parsedown.php create mode 100644 html/includes/readme-markdown.php diff --git a/html/header.php b/html/header.php index 2d2edae..9d7cde4 100644 --- a/html/header.php +++ b/html/header.php @@ -85,6 +85,7 @@ } require ("includes/search-breadcrumbs-theme.php"); if (! preg_match (":^/((html/)?donors.php|(html/)?s(\.shtml)?(\?.*)?|(html/)?search(\.shtml)?(\?.*))$:", $_SERVER['REQUEST_URI']) && ! preg_match (":^4..$:", $_SERVER['REDIRECT_STATUS'])) { + require ("includes/readme-markdown.php"); ?>
diff --git a/html/includes/Parsedown.php b/html/includes/Parsedown.php new file mode 100644 index 0000000..1b9d6d5 --- /dev/null +++ b/html/includes/Parsedown.php @@ -0,0 +1,1712 @@ +DefinitionData = array(); + + # standardize line breaks + $text = str_replace(array("\r\n", "\r"), "\n", $text); + + # remove surrounding line breaks + $text = trim($text, "\n"); + + # split text into lines + $lines = explode("\n", $text); + + # iterate through lines to identify blocks + $markup = $this->lines($lines); + + # trim line breaks + $markup = trim($markup, "\n"); + + return $markup; + } + + # + # Setters + # + + function setBreaksEnabled($breaksEnabled) + { + $this->breaksEnabled = $breaksEnabled; + + return $this; + } + + protected $breaksEnabled; + + function setMarkupEscaped($markupEscaped) + { + $this->markupEscaped = $markupEscaped; + + return $this; + } + + protected $markupEscaped; + + function setUrlsLinked($urlsLinked) + { + $this->urlsLinked = $urlsLinked; + + return $this; + } + + protected $urlsLinked = true; + + function setSafeMode($safeMode) + { + $this->safeMode = (bool) $safeMode; + + return $this; + } + + protected $safeMode; + + protected $safeLinksWhitelist = array( + 'http://', + 'https://', + 'ftp://', + 'ftps://', + 'mailto:', + 'data:image/png;base64,', + 'data:image/gif;base64,', + 'data:image/jpeg;base64,', + 'irc:', + 'ircs:', + 'git:', + 'ssh:', + 'news:', + 'steam:', + ); + + # + # Lines + # + + protected $BlockTypes = array( + '#' => array('Header'), + '*' => array('Rule', 'List'), + '+' => array('List'), + '-' => array('SetextHeader', 'Table', 'Rule', 'List'), + '0' => array('List'), + '1' => array('List'), + '2' => array('List'), + '3' => array('List'), + '4' => array('List'), + '5' => array('List'), + '6' => array('List'), + '7' => array('List'), + '8' => array('List'), + '9' => array('List'), + ':' => array('Table'), + '<' => array('Comment', 'Markup'), + '=' => array('SetextHeader'), + '>' => array('Quote'), + '[' => array('Reference'), + '_' => array('Rule'), + '`' => array('FencedCode'), + '|' => array('Table'), + '~' => array('FencedCode'), + ); + + # ~ + + protected $unmarkedBlockTypes = array( + 'Code', + ); + + # + # Blocks + # + + protected function lines(array $lines) + { + $CurrentBlock = null; + + foreach ($lines as $line) + { + if (chop($line) === '') + { + if (isset($CurrentBlock)) + { + $CurrentBlock['interrupted'] = true; + } + + continue; + } + + if (strpos($line, "\t") !== false) + { + $parts = explode("\t", $line); + + $line = $parts[0]; + + unset($parts[0]); + + foreach ($parts as $part) + { + $shortage = 4 - mb_strlen($line, 'utf-8') % 4; + + $line .= str_repeat(' ', $shortage); + $line .= $part; + } + } + + $indent = 0; + + while (isset($line[$indent]) and $line[$indent] === ' ') + { + $indent ++; + } + + $text = $indent > 0 ? substr($line, $indent) : $line; + + # ~ + + $Line = array('body' => $line, 'indent' => $indent, 'text' => $text); + + # ~ + + if (isset($CurrentBlock['continuable'])) + { + $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock); + + if (isset($Block)) + { + $CurrentBlock = $Block; + + continue; + } + else + { + if ($this->isBlockCompletable($CurrentBlock['type'])) + { + $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock); + } + } + } + + # ~ + + $marker = $text[0]; + + # ~ + + $blockTypes = $this->unmarkedBlockTypes; + + if (isset($this->BlockTypes[$marker])) + { + foreach ($this->BlockTypes[$marker] as $blockType) + { + $blockTypes []= $blockType; + } + } + + # + # ~ + + foreach ($blockTypes as $blockType) + { + $Block = $this->{'block'.$blockType}($Line, $CurrentBlock); + + if (isset($Block)) + { + $Block['type'] = $blockType; + + if ( ! isset($Block['identified'])) + { + $Blocks []= $CurrentBlock; + + $Block['identified'] = true; + } + + if ($this->isBlockContinuable($blockType)) + { + $Block['continuable'] = true; + } + + $CurrentBlock = $Block; + + continue 2; + } + } + + # ~ + + if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted'])) + { + $CurrentBlock['element']['text'] .= "\n".$text; + } + else + { + $Blocks []= $CurrentBlock; + + $CurrentBlock = $this->paragraph($Line); + + $CurrentBlock['identified'] = true; + } + } + + # ~ + + if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type'])) + { + $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock); + } + + # ~ + + $Blocks []= $CurrentBlock; + + unset($Blocks[0]); + + # ~ + + $markup = ''; + + foreach ($Blocks as $Block) + { + if (isset($Block['hidden'])) + { + continue; + } + + $markup .= "\n"; + $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']); + } + + $markup .= "\n"; + + # ~ + + return $markup; + } + + protected function isBlockContinuable($Type) + { + return method_exists($this, 'block'.$Type.'Continue'); + } + + protected function isBlockCompletable($Type) + { + return method_exists($this, 'block'.$Type.'Complete'); + } + + # + # Code + + protected function blockCode($Line, $Block = null) + { + if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted'])) + { + return; + } + + if ($Line['indent'] >= 4) + { + $text = substr($Line['body'], 4); + + $Block = array( + 'element' => array( + 'name' => 'pre', + 'handler' => 'element', + 'text' => array( + 'name' => 'code', + 'text' => $text, + ), + ), + ); + + return $Block; + } + } + + protected function blockCodeContinue($Line, $Block) + { + if ($Line['indent'] >= 4) + { + if (isset($Block['interrupted'])) + { + $Block['element']['text']['text'] .= "\n"; + + unset($Block['interrupted']); + } + + $Block['element']['text']['text'] .= "\n"; + + $text = substr($Line['body'], 4); + + $Block['element']['text']['text'] .= $text; + + return $Block; + } + } + + protected function blockCodeComplete($Block) + { + $text = $Block['element']['text']['text']; + + $Block['element']['text']['text'] = $text; + + return $Block; + } + + # + # Comment + + protected function blockComment($Line) + { + if ($this->markupEscaped or $this->safeMode) + { + return; + } + + if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!') + { + $Block = array( + 'markup' => $Line['body'], + ); + + if (preg_match('/-->$/', $Line['text'])) + { + $Block['closed'] = true; + } + + return $Block; + } + } + + protected function blockCommentContinue($Line, array $Block) + { + if (isset($Block['closed'])) + { + return; + } + + $Block['markup'] .= "\n" . $Line['body']; + + if (preg_match('/-->$/', $Line['text'])) + { + $Block['closed'] = true; + } + + return $Block; + } + + # + # Fenced Code + + protected function blockFencedCode($Line) + { + if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([^`]+)?[ ]*$/', $Line['text'], $matches)) + { + $Element = array( + 'name' => 'code', + 'text' => '', + ); + + if (isset($matches[1])) + { + /** + * https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#classes + * Every HTML element may have a class attribute specified. + * The attribute, if specified, must have a value that is a set + * of space-separated tokens representing the various classes + * that the element belongs to. + * [...] + * The space characters, for the purposes of this specification, + * are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab), + * U+000A LINE FEED (LF), U+000C FORM FEED (FF), and + * U+000D CARRIAGE RETURN (CR). + */ + $language = substr($matches[1], 0, strcspn($matches[1], " \t\n\f\r")); + + $class = 'language-'.$language; + + $Element['attributes'] = array( + 'class' => $class, + ); + } + + $Block = array( + 'char' => $Line['text'][0], + 'element' => array( + 'name' => 'pre', + 'handler' => 'element', + 'text' => $Element, + ), + ); + + return $Block; + } + } + + protected function blockFencedCodeContinue($Line, $Block) + { + if (isset($Block['complete'])) + { + return; + } + + if (isset($Block['interrupted'])) + { + $Block['element']['text']['text'] .= "\n"; + + unset($Block['interrupted']); + } + + if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text'])) + { + $Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1); + + $Block['complete'] = true; + + return $Block; + } + + $Block['element']['text']['text'] .= "\n".$Line['body']; + + return $Block; + } + + protected function blockFencedCodeComplete($Block) + { + $text = $Block['element']['text']['text']; + + $Block['element']['text']['text'] = $text; + + return $Block; + } + + # + # Header + + protected function blockHeader($Line) + { + if (isset($Line['text'][1])) + { + $level = 1; + + while (isset($Line['text'][$level]) and $Line['text'][$level] === '#') + { + $level ++; + } + + if ($level > 6) + { + return; + } + + $text = trim($Line['text'], '# '); + + $Block = array( + 'element' => array( + 'name' => 'h' . min(6, $level), + 'text' => $text, + 'handler' => 'line', + ), + ); + + return $Block; + } + } + + # + # List + + protected function blockList($Line) + { + list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]'); + + if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches)) + { + $Block = array( + 'indent' => $Line['indent'], + 'pattern' => $pattern, + 'element' => array( + 'name' => $name, + 'handler' => 'elements', + ), + ); + + if($name === 'ol') + { + $listStart = stristr($matches[0], '.', true); + + if($listStart !== '1') + { + $Block['element']['attributes'] = array('start' => $listStart); + } + } + + $Block['li'] = array( + 'name' => 'li', + 'handler' => 'li', + 'text' => array( + $matches[2], + ), + ); + + $Block['element']['text'] []= & $Block['li']; + + return $Block; + } + } + + protected function blockListContinue($Line, array $Block) + { + if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches)) + { + if (isset($Block['interrupted'])) + { + $Block['li']['text'] []= ''; + + $Block['loose'] = true; + + unset($Block['interrupted']); + } + + unset($Block['li']); + + $text = isset($matches[1]) ? $matches[1] : ''; + + $Block['li'] = array( + 'name' => 'li', + 'handler' => 'li', + 'text' => array( + $text, + ), + ); + + $Block['element']['text'] []= & $Block['li']; + + return $Block; + } + + if ($Line['text'][0] === '[' and $this->blockReference($Line)) + { + return $Block; + } + + if ( ! isset($Block['interrupted'])) + { + $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']); + + $Block['li']['text'] []= $text; + + return $Block; + } + + if ($Line['indent'] > 0) + { + $Block['li']['text'] []= ''; + + $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']); + + $Block['li']['text'] []= $text; + + unset($Block['interrupted']); + + return $Block; + } + } + + protected function blockListComplete(array $Block) + { + if (isset($Block['loose'])) + { + foreach ($Block['element']['text'] as &$li) + { + if (end($li['text']) !== '') + { + $li['text'] []= ''; + } + } + } + + return $Block; + } + + # + # Quote + + protected function blockQuote($Line) + { + if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) + { + $Block = array( + 'element' => array( + 'name' => 'blockquote', + 'handler' => 'lines', + 'text' => (array) $matches[1], + ), + ); + + return $Block; + } + } + + protected function blockQuoteContinue($Line, array $Block) + { + if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) + { + if (isset($Block['interrupted'])) + { + $Block['element']['text'] []= ''; + + unset($Block['interrupted']); + } + + $Block['element']['text'] []= $matches[1]; + + return $Block; + } + + if ( ! isset($Block['interrupted'])) + { + $Block['element']['text'] []= $Line['text']; + + return $Block; + } + } + + # + # Rule + + protected function blockRule($Line) + { + if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text'])) + { + $Block = array( + 'element' => array( + 'name' => 'hr' + ), + ); + + return $Block; + } + } + + # + # Setext + + protected function blockSetextHeader($Line, array $Block = null) + { + if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) + { + return; + } + + if (chop($Line['text'], $Line['text'][0]) === '') + { + $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2'; + + return $Block; + } + } + + # + # Markup + + protected function blockMarkup($Line) + { + if ($this->markupEscaped or $this->safeMode) + { + return; + } + + if (preg_match('/^<(\w[\w-]*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches)) + { + $element = strtolower($matches[1]); + + if (in_array($element, $this->textLevelElements)) + { + return; + } + + $Block = array( + 'name' => $matches[1], + 'depth' => 0, + 'markup' => $Line['text'], + ); + + $length = strlen($matches[0]); + + $remainder = substr($Line['text'], $length); + + if (trim($remainder) === '') + { + if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) + { + $Block['closed'] = true; + + $Block['void'] = true; + } + } + else + { + if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) + { + return; + } + + if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder)) + { + $Block['closed'] = true; + } + } + + return $Block; + } + } + + protected function blockMarkupContinue($Line, array $Block) + { + if (isset($Block['closed'])) + { + return; + } + + if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open + { + $Block['depth'] ++; + } + + if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close + { + if ($Block['depth'] > 0) + { + $Block['depth'] --; + } + else + { + $Block['closed'] = true; + } + } + + if (isset($Block['interrupted'])) + { + $Block['markup'] .= "\n"; + + unset($Block['interrupted']); + } + + $Block['markup'] .= "\n".$Line['body']; + + return $Block; + } + + # + # Reference + + protected function blockReference($Line) + { + if (preg_match('/^\[(.+?)\]:[ ]*?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches)) + { + $id = strtolower($matches[1]); + + $Data = array( + 'url' => $matches[2], + 'title' => null, + ); + + if (isset($matches[3])) + { + $Data['title'] = $matches[3]; + } + + $this->DefinitionData['Reference'][$id] = $Data; + + $Block = array( + 'hidden' => true, + ); + + return $Block; + } + } + + # + # Table + + protected function blockTable($Line, array $Block = null) + { + if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) + { + return; + } + + if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '') + { + $alignments = array(); + + $divider = $Line['text']; + + $divider = trim($divider); + $divider = trim($divider, '|'); + + $dividerCells = explode('|', $divider); + + foreach ($dividerCells as $dividerCell) + { + $dividerCell = trim($dividerCell); + + if ($dividerCell === '') + { + continue; + } + + $alignment = null; + + if ($dividerCell[0] === ':') + { + $alignment = 'left'; + } + + if (substr($dividerCell, - 1) === ':') + { + $alignment = $alignment === 'left' ? 'center' : 'right'; + } + + $alignments []= $alignment; + } + + # ~ + + $HeaderElements = array(); + + $header = $Block['element']['text']; + + $header = trim($header); + $header = trim($header, '|'); + + $headerCells = explode('|', $header); + + foreach ($headerCells as $index => $headerCell) + { + $headerCell = trim($headerCell); + + $HeaderElement = array( + 'name' => 'th', + 'text' => $headerCell, + 'handler' => 'line', + ); + + if (isset($alignments[$index])) + { + $alignment = $alignments[$index]; + + $HeaderElement['attributes'] = array( + 'style' => 'text-align: '.$alignment.';', + ); + } + + $HeaderElements []= $HeaderElement; + } + + # ~ + + $Block = array( + 'alignments' => $alignments, + 'identified' => true, + 'element' => array( + 'name' => 'table', + 'handler' => 'elements', + ), + ); + + $Block['element']['text'] []= array( + 'name' => 'thead', + 'handler' => 'elements', + ); + + $Block['element']['text'] []= array( + 'name' => 'tbody', + 'handler' => 'elements', + 'text' => array(), + ); + + $Block['element']['text'][0]['text'] []= array( + 'name' => 'tr', + 'handler' => 'elements', + 'text' => $HeaderElements, + ); + + return $Block; + } + } + + protected function blockTableContinue($Line, array $Block) + { + if (isset($Block['interrupted'])) + { + return; + } + + if ($Line['text'][0] === '|' or strpos($Line['text'], '|')) + { + $Elements = array(); + + $row = $Line['text']; + + $row = trim($row); + $row = trim($row, '|'); + + preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches); + + foreach ($matches[0] as $index => $cell) + { + $cell = trim($cell); + + $Element = array( + 'name' => 'td', + 'handler' => 'line', + 'text' => $cell, + ); + + if (isset($Block['alignments'][$index])) + { + $Element['attributes'] = array( + 'style' => 'text-align: '.$Block['alignments'][$index].';', + ); + } + + $Elements []= $Element; + } + + $Element = array( + 'name' => 'tr', + 'handler' => 'elements', + 'text' => $Elements, + ); + + $Block['element']['text'][1]['text'] []= $Element; + + return $Block; + } + } + + # + # ~ + # + + protected function paragraph($Line) + { + $Block = array( + 'element' => array( + 'name' => 'p', + 'text' => $Line['text'], + 'handler' => 'line', + ), + ); + + return $Block; + } + + # + # Inline Elements + # + + protected $InlineTypes = array( + '"' => array('SpecialCharacter'), + '!' => array('Image'), + '&' => array('SpecialCharacter'), + '*' => array('Emphasis'), + ':' => array('Url'), + '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'), + '>' => array('SpecialCharacter'), + '[' => array('Link'), + '_' => array('Emphasis'), + '`' => array('Code'), + '~' => array('Strikethrough'), + '\\' => array('EscapeSequence'), + ); + + # ~ + + protected $inlineMarkerList = '!"*_&[:<>`~\\'; + + # + # ~ + # + + public function line($text, $nonNestables=array()) + { + $markup = ''; + + # $excerpt is based on the first occurrence of a marker + + while ($excerpt = strpbrk($text, $this->inlineMarkerList)) + { + $marker = $excerpt[0]; + + $markerPosition = strpos($text, $marker); + + $Excerpt = array('text' => $excerpt, 'context' => $text); + + foreach ($this->InlineTypes[$marker] as $inlineType) + { + # check to see if the current inline type is nestable in the current context + + if ( ! empty($nonNestables) and in_array($inlineType, $nonNestables)) + { + continue; + } + + $Inline = $this->{'inline'.$inlineType}($Excerpt); + + if ( ! isset($Inline)) + { + continue; + } + + # makes sure that the inline belongs to "our" marker + + if (isset($Inline['position']) and $Inline['position'] > $markerPosition) + { + continue; + } + + # sets a default inline position + + if ( ! isset($Inline['position'])) + { + $Inline['position'] = $markerPosition; + } + + # cause the new element to 'inherit' our non nestables + + foreach ($nonNestables as $non_nestable) + { + $Inline['element']['nonNestables'][] = $non_nestable; + } + + # the text that comes before the inline + $unmarkedText = substr($text, 0, $Inline['position']); + + # compile the unmarked text + $markup .= $this->unmarkedText($unmarkedText); + + # compile the inline + $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']); + + # remove the examined text + $text = substr($text, $Inline['position'] + $Inline['extent']); + + continue 2; + } + + # the marker does not belong to an inline + + $unmarkedText = substr($text, 0, $markerPosition + 1); + + $markup .= $this->unmarkedText($unmarkedText); + + $text = substr($text, $markerPosition + 1); + } + + $markup .= $this->unmarkedText($text); + + return $markup; + } + + # + # ~ + # + + protected function inlineCode($Excerpt) + { + $marker = $Excerpt['text'][0]; + + if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(? strlen($matches[0]), + 'element' => array( + 'name' => 'code', + 'text' => $text, + ), + ); + } + } + + protected function inlineEmailTag($Excerpt) + { + if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches)) + { + $url = $matches[1]; + + if ( ! isset($matches[2])) + { + $url = 'mailto:' . $url; + } + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'a', + 'text' => $matches[1], + 'attributes' => array( + 'href' => $url, + ), + ), + ); + } + } + + protected function inlineEmphasis($Excerpt) + { + if ( ! isset($Excerpt['text'][1])) + { + return; + } + + $marker = $Excerpt['text'][0]; + + if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) + { + $emphasis = 'strong'; + } + elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) + { + $emphasis = 'em'; + } + else + { + return; + } + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => $emphasis, + 'handler' => 'line', + 'text' => $matches[1], + ), + ); + } + + protected function inlineEscapeSequence($Excerpt) + { + if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) + { + return array( + 'markup' => $Excerpt['text'][1], + 'extent' => 2, + ); + } + } + + protected function inlineImage($Excerpt) + { + if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[') + { + return; + } + + $Excerpt['text']= substr($Excerpt['text'], 1); + + $Link = $this->inlineLink($Excerpt); + + if ($Link === null) + { + return; + } + + $Inline = array( + 'extent' => $Link['extent'] + 1, + 'element' => array( + 'name' => 'img', + 'attributes' => array( + 'src' => $Link['element']['attributes']['href'], + 'alt' => $Link['element']['text'], + ), + ), + ); + + $Inline['element']['attributes'] += $Link['element']['attributes']; + + unset($Inline['element']['attributes']['href']); + + return $Inline; + } + + protected function inlineLink($Excerpt) + { + $Element = array( + 'name' => 'a', + 'handler' => 'line', + 'nonNestables' => array('Url', 'Link'), + 'text' => null, + 'attributes' => array( + 'href' => null, + 'title' => null, + ), + ); + + $extent = 0; + + $remainder = $Excerpt['text']; + + if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches)) + { + $Element['text'] = $matches[1]; + + $extent += strlen($matches[0]); + + $remainder = substr($remainder, $extent); + } + else + { + return; + } + + if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\s*[)]/', $remainder, $matches)) + { + $Element['attributes']['href'] = $matches[1]; + + if (isset($matches[2])) + { + $Element['attributes']['title'] = substr($matches[2], 1, - 1); + } + + $extent += strlen($matches[0]); + } + else + { + if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches)) + { + $definition = strlen($matches[1]) ? $matches[1] : $Element['text']; + $definition = strtolower($definition); + + $extent += strlen($matches[0]); + } + else + { + $definition = strtolower($Element['text']); + } + + if ( ! isset($this->DefinitionData['Reference'][$definition])) + { + return; + } + + $Definition = $this->DefinitionData['Reference'][$definition]; + + $Element['attributes']['href'] = $Definition['url']; + $Element['attributes']['title'] = $Definition['title']; + } + + return array( + 'extent' => $extent, + 'element' => $Element, + ); + } + + protected function inlineMarkup($Excerpt) + { + if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false) + { + return; + } + + if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*[ ]*>/s', $Excerpt['text'], $matches)) + { + return array( + 'markup' => $matches[0], + 'extent' => strlen($matches[0]), + ); + } + + if ($Excerpt['text'][1] === '!' and preg_match('/^/s', $Excerpt['text'], $matches)) + { + return array( + 'markup' => $matches[0], + 'extent' => strlen($matches[0]), + ); + } + + if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches)) + { + return array( + 'markup' => $matches[0], + 'extent' => strlen($matches[0]), + ); + } + } + + protected function inlineSpecialCharacter($Excerpt) + { + if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text'])) + { + return array( + 'markup' => '&', + 'extent' => 1, + ); + } + + $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot'); + + if (isset($SpecialCharacter[$Excerpt['text'][0]])) + { + return array( + 'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';', + 'extent' => 1, + ); + } + } + + protected function inlineStrikethrough($Excerpt) + { + if ( ! isset($Excerpt['text'][1])) + { + return; + } + + if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches)) + { + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'del', + 'text' => $matches[1], + 'handler' => 'line', + ), + ); + } + } + + protected function inlineUrl($Excerpt) + { + if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/') + { + return; + } + + if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)) + { + $url = $matches[0][0]; + + $Inline = array( + 'extent' => strlen($matches[0][0]), + 'position' => $matches[0][1], + 'element' => array( + 'name' => 'a', + 'text' => $url, + 'attributes' => array( + 'href' => $url, + ), + ), + ); + + return $Inline; + } + } + + protected function inlineUrlTag($Excerpt) + { + if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches)) + { + $url = $matches[1]; + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'a', + 'text' => $url, + 'attributes' => array( + 'href' => $url, + ), + ), + ); + } + } + + # ~ + + protected function unmarkedText($text) + { + if ($this->breaksEnabled) + { + $text = preg_replace('/[ ]*\n/', "
\n", $text); + } + else + { + $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "
\n", $text); + $text = str_replace(" \n", "\n", $text); + } + + return $text; + } + + # + # Handlers + # + + protected function element(array $Element) + { + if ($this->safeMode) + { + $Element = $this->sanitiseElement($Element); + } + + $markup = '<'.$Element['name']; + + if (isset($Element['attributes'])) + { + foreach ($Element['attributes'] as $name => $value) + { + if ($value === null) + { + continue; + } + + $markup .= ' '.$name.'="'.self::escape($value).'"'; + } + } + + $permitRawHtml = false; + + if (isset($Element['text'])) + { + $text = $Element['text']; + } + // very strongly consider an alternative if you're writing an + // extension + elseif (isset($Element['rawHtml'])) + { + $text = $Element['rawHtml']; + $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode']; + $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode; + } + + if (isset($text)) + { + $markup .= '>'; + + if (!isset($Element['nonNestables'])) + { + $Element['nonNestables'] = array(); + } + + if (isset($Element['handler'])) + { + $markup .= $this->{$Element['handler']}($text, $Element['nonNestables']); + } + elseif (!$permitRawHtml) + { + $markup .= self::escape($text, true); + } + else + { + $markup .= $text; + } + + $markup .= ''; + } + else + { + $markup .= ' />'; + } + + return $markup; + } + + protected function elements(array $Elements) + { + $markup = ''; + + foreach ($Elements as $Element) + { + $markup .= "\n" . $this->element($Element); + } + + $markup .= "\n"; + + return $markup; + } + + # ~ + + protected function li($lines) + { + $markup = $this->lines($lines); + + $trimmedMarkup = trim($markup); + + if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '

') + { + $markup = $trimmedMarkup; + $markup = substr($markup, 3); + + $position = strpos($markup, "

"); + + $markup = substr_replace($markup, '', $position, 4); + } + + return $markup; + } + + # + # Deprecated Methods + # + + function parse($text) + { + $markup = $this->text($text); + + return $markup; + } + + protected function sanitiseElement(array $Element) + { + static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/'; + static $safeUrlNameToAtt = array( + 'a' => 'href', + 'img' => 'src', + ); + + if (isset($safeUrlNameToAtt[$Element['name']])) + { + $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]); + } + + if ( ! empty($Element['attributes'])) + { + foreach ($Element['attributes'] as $att => $val) + { + # filter out badly parsed attribute + if ( ! preg_match($goodAttribute, $att)) + { + unset($Element['attributes'][$att]); + } + # dump onevent attribute + elseif (self::striAtStart($att, 'on')) + { + unset($Element['attributes'][$att]); + } + } + } + + return $Element; + } + + protected function filterUnsafeUrlInAttribute(array $Element, $attribute) + { + foreach ($this->safeLinksWhitelist as $scheme) + { + if (self::striAtStart($Element['attributes'][$attribute], $scheme)) + { + return $Element; + } + } + + $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]); + + return $Element; + } + + # + # Static Methods + # + + protected static function escape($text, $allowQuotes = false) + { + return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8'); + } + + protected static function striAtStart($string, $needle) + { + $len = strlen($needle); + + if ($len > strlen($string)) + { + return false; + } + else + { + return strtolower(substr($string, 0, $len)) === strtolower($needle); + } + } + + static function instance($name = 'default') + { + if (isset(self::$instances[$name])) + { + return self::$instances[$name]; + } + + $instance = new static(); + + self::$instances[$name] = $instance; + + return $instance; + } + + private static $instances = array(); + + # + # Fields + # + + protected $DefinitionData; + + # + # Read-Only + + protected $specialCharacters = array( + '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|', + ); + + protected $StrongRegex = array( + '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s', + '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us', + ); + + protected $EmRegex = array( + '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', + '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us', + ); + + protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?'; + + protected $voidElements = array( + 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', + ); + + protected $textLevelElements = array( + 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont', + 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing', + 'i', 'rp', 'del', 'code', 'strike', 'marquee', + 'q', 'rt', 'ins', 'font', 'strong', + 's', 'tt', 'kbd', 'mark', + 'u', 'xm', 'sub', 'nobr', + 'sup', 'ruby', + 'var', 'span', + 'wbr', 'time', + ); +} diff --git a/html/includes/readme-markdown.php b/html/includes/readme-markdown.php new file mode 100644 index 0000000..b26ec56 --- /dev/null +++ b/html/includes/readme-markdown.php @@ -0,0 +1,14 @@ +'); + print ('
Content of directory\'s README.md
'); + print ('
'); + print ($Parsedown->text ($readme)); + print ("
"); + print ("
"); + } +?> From 47a141db23667827cdf92caaa87d141562cd588a Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Mon, 6 Oct 2025 18:03:16 +0100 Subject: [PATCH 08/10] Update donations information/logos. --- html/includes/donate.php | 20 ++++++++++++++++---- html/paypal-black.png | Bin 16510 -> 5411 bytes html/paypal-white.png | Bin 12211 -> 5311 bytes 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/html/includes/donate.php b/html/includes/donate.php index 25e1d96..222361c 100644 --- a/html/includes/donate.php +++ b/html/includes/donate.php @@ -1,9 +1,21 @@
- Patreon Logo - PayPal Logo +
+ Patreon Logo
+ For regular monthly donations +
+
+ PayPal Logo
+ For one time donations +
- Patreon Logo - PayPal Logo +
+ Patreon Logo
+ For regular monthly donations +
+
+ PayPal Logo
+ For one time donations +
diff --git a/html/paypal-black.png b/html/paypal-black.png index e0faea91e61e18fb15497a0c382caa1c526f6ae9..e4a7e2a4c189fd91e9584952f354e83b847592a6 100644 GIT binary patch delta 4662 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%0D3Z1jKE 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 diff --git a/html/paypal-white.png b/html/paypal-white.png index 0a31c88a8e0215336dbc91a5c2b61e4e9d4d178b..8b97cd138f88fd8f6212f0fefbc0d3872a9097dd 100644 GIT binary patch delta 4558 zcmV;<5i#zwU%x4TiBL{Q4GJ0x0000DNk~Le0002|0000*2m=5B09mkm=l}o!0drDE zLIK&yEPnt100d`2O+f$vv5yPfP?@5`Tzg`fam}Kbua(` z>RI+y?e7jT@qQ9J+u0{~D=R7F()08D9d00000008;3-WUf1lkyuIf9VGp4-XgB z1)aYD01*61L_t(|+U1=4QVU0q9OsQ1P6XxsKEaub5msRb8p zyV~tGRkV%{(CrODyWAiW&A>L5^kOz?ld9Qh1&FyYTbV@CkdP`!AO?H~QW25RgiE!! zUA48(x#S8$Le2Cx?zfD2f6qD3bI$pk^PI~|i9FsKx|5Z$xs}D+plJr8fUb!=v}-Fdi+%;K)IM^iy>lgUuLeAl8b zK3-H`^~q+ca`dv zJqT;hI`H4Y7=71TT=W@uy*2vuRMFkGT|l<>;zt4BT66K#=~J6Qr>QXE=`*KK!PDwJ zKaKF$p8VUe%{^?qa_Lm6YwD8(Me<@F`tV8gvswmCBvqDz=ksNv=Y~1ZbHnl}^m#*1 zPgNbO_yaoq-n7fZf5^05DBO{Ts^YZc(kGWL?bxuY5|fv9tXJ2i<)<&OmV-8n&0|;y ze&*$Zr{C;Q*woVeCi)Cu?>Jun`_#3=`^*;8Gf&^R;d#~XH>Rq&7x8-fa&Ecmck6gO z&I2{PcwXqWc$b&|d%^4ZpS~SyIMv_lkgZOi1&3kXmHM!5!@D^LRXceL-*6ty^I3H(>cAwcP45M00NW`w7Yv z%J9CVVbJgw|E({fuDO>_v0ly@qCM&wB{p-B9^udG9Zt~Ahs_D}*|6DNKNhDe&4E`QD1sWP6+d$sqacuJPE1Vj=mv+Bv ze{0S%**Wn$eZjqSRp22}Z<`?L2^#iXU}8|z-Yyv%85|sW#1i~RfqTQV2wvC|z)e+# zi1lCq`}PyIr?eY%6*Tnw4NvkK@_L;R`_9LdehL~a7@oo&z2oWkyP%*>7K?jW@udZo z>1ucchpjj?42goTCp-#r)$vqLj!A5xe@S-$H0kNVxu(g=;XeG-K8c(QCdcT(h#NN0 zs2|5Q7fg`t56}w6dwcuG-CiX33$g;7-U2WoLowy8+<+=}F
s4qWPc{x2*y2?IBd+BWpx~N3ODxM18|!fA8ht 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 delta 11518 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 From 5e340c6597928f41f52a621fd58c04a7eec62bf4 Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Mon, 6 Oct 2025 18:03:35 +0100 Subject: [PATCH 09/10] Update donors list. --- html/donors.php | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/html/donors.php b/html/donors.php index d7f9a6b..44fa7e5 100644 --- a/html/donors.php +++ b/html/donors.php @@ -13,6 +13,63 @@
12th January 2025Alain Detal
4th December 2024Syed Sajjad Rizvi
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 3ba9bd8e752ec14c196ad935c587de75491b16b4 Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Mon, 6 Oct 2025 18:57:00 +0100 Subject: [PATCH 10/10] Update vars.php. --- html/includes/vars.php | 52 +++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/html/includes/vars.php b/html/includes/vars.php index 78db42d..1783975 100644 --- a/html/includes/vars.php +++ b/html/includes/vars.php @@ -6,11 +6,11 @@ $keywords = "Slackware UK, Slackware64 UK, Slackware, Slackware64, Slackware Linux, Slackware mirror, Slackware mirrors, Slackware hosting"; } elseif (preg_match (":^/s(earch)?(\?.*)?$:", $_SERVER['REQUEST_URI'])) { $title = "Search Results"; - $description = "Search Results"; + $description = "Search results"; $keywords = "Slackware Linux, Slackware mirror, Slackware mirrors, Slackware hosting, Slackware, Slackware64, Slackware UK, Slackware64 UK"; } elseif (preg_match (":^/html/search\.shtml(\?.*)?$:", $_SERVER['REQUEST_URI'])) { $title = "Search Results"; - $description = "Search Results"; + $description = "Search results"; $keywords = "Slackware Linux, Slackware mirror, Slackware mirrors, Slackware hosting, Slackware, Slackware64, Slackware UK, Slackware64 UK"; } elseif (preg_match (":^/html/errordocs/.*:", $_SERVER['REQUEST_URI'])) { $title = "Error"; @@ -18,12 +18,16 @@ $keywords = "Slackware Linux, Slackware mirror, Slackware mirrors, Slackware hosting, Slackware, Slackware64, Slackware UK, Slackware64 UK"; } elseif (preg_match (":^/html/donors\.php$:", $_SERVER['REQUEST_URI'])) { $title = "Project Supporters"; - $description = "The people who have made PayPal donations to the project."; + $description = "The people who have made PayPal donations to the project"; $keywords = "Slackware Linux, Slackware mirror, Slackware mirrors, Slackware hosting, Slackware, Slackware64, Slackware UK, Slackware64 UK"; } elseif (preg_match (":^/absolute/.*:", $_SERVER['REQUEST_URI'])) { $title = "Absolute Linux"; $description = "Absolute Linux"; $keywords = "Absolute Linux, Absolute, Absolute Linux mirror, Absolute mirror"; + } elseif (preg_match (":^/bonappetit/.*:", $_SERVER['REQUEST_URI'])) { + $title = "Bonappetit"; + $description = "Bonappetit tools for the kitchen enthusiast"; + $keywords = "Bonappetit, Slackware Food, Slackware Kitchen, Slackware Bonappetit"; } elseif (preg_match (":^/csb/.*:", $_SERVER['REQUEST_URI'])) { $title = "Cinnamon SlackBuild (CSB)"; $description = "Cinnamon desktop environment for Slackware"; @@ -36,30 +40,22 @@ $title = "Freeslack"; $description = "Slackware with all proprietary components removed"; $keywords = "Freeslack, Slackware freedom, Slackware unencumbered, Slackware non-proprietary"; - } elseif (preg_match (":^/gfs/.*:", $_SERVER['REQUEST_URI'])) { - $title = "GNOME From Scratch (GFS)"; - $description = "GNOME desktop environment for Slackware"; - $keywords = "GNOME Slackware, GFS, GNOME desktop Slackware, GNOME desktop environment Slackware"; } elseif (preg_match (":^/gsb/.*:", $_SERVER['REQUEST_URI'])) { $title = "GNOME SlackBuild (GSB)"; $description = "GSB desktop environment for Slackware (abandoned)"; $keywords = "GNOME SlackBuild, GSB, GNOME Slackware, GSB Slackware, GNOME desktop Slackware, GNOME desktop environment Slackware"; } elseif (preg_match (":^/liveslak/.*:", $_SERVER['REQUEST_URI'])) { - $title = "AlienBOB's Liveslak (Slackware Live Edition)"; + $title = "AlienBOB's LiveSlak (Slackware Live Edition)"; $description = "A Slackware Linux 'live' environment"; $keywords = "Liveslak, Slackware Live Edition, Slackware Live"; } elseif (preg_match (":^/microlinux/.*:", $_SERVER['REQUEST_URI'])) { $title = "Microlinux"; - $description = "Microlinux Enterprise Desktop and Server (abandoned)"; + $description = "Microlinux enterprise desktop and server (abandoned)"; $keywords = "Microlinux, Microlinux Enterprise, Microlinux Enterprise Desktop, Microlinux Enterprise Server, MLED, MLES, Microlinux Slackware"; } elseif (preg_match (":^/msb/.*:", $_SERVER['REQUEST_URI'])) { $title = "MATE SlackBuild (MSB)"; $description = "MATE desktop environment for Slackware"; $keywords = "MATE SlackBuild, MSB, MATE Slackware, MATE desktop Slackware, MATE desktop environment Slackware"; - } elseif ($_SERVER['REQUEST_URI'] == "/people/") { - $title = "SlackBuilds and packages from people"; - $description = "SlackBuilds and packages from individual people"; - $keywords = "Slackware people, alienBOB Slackware, rworkman Slackware, rlworkman Slackware, alphageek Slackware, alienBOB, rworkman, rlworkman, alphageek"; } elseif (preg_match (":^/people/alien/.*:", $_SERVER['REQUEST_URI'])) { $title = "AlienBOB's SlackBuilds and Packages"; $description = "AlienBOB's SlackBuilds and packages"; @@ -74,16 +70,12 @@ $keywords = "alienBOB current ISO, alienBOB Slackware current, alienBOB Slackware64 current, alienBOB Slackware-current, alienBOB Slackware64-current, alienBOB Slackware current ISO, alienBOB Slackware64 current ISO, alienBOB Slackware-current ISO, alienBOB Slackware64-current ISO, Slackware current ISO, Slackware64 current ISO, current ISO"; } elseif (preg_match (":^/people/alien-kde/.*:", $_SERVER['REQUEST_URI'])) { $title = "AlienBOB's 'Ktown' KDE Builds"; - $description = "AlienBOB's 'ktown' KDE builds for Slackware"; + $description = "AlienBOB's 'Ktown' KDE builds for Slackware"; $keywords = "alienBOB KDE, alienBOB ktown, alienBOB Slackware KDE, alienBOB Slackware ktown, Slackware KDE, Slackware ktown"; } elseif (preg_match (":^/people/alien-openvz/.*:", $_SERVER['REQUEST_URI'])) { $title = "AlienBOB's OpenVZ Container Template"; $description = "AlienBOB's OpenVZ container template images (abandoned)"; $keywords = "alienBOB OpenVZ, alienBOB Slackware OpenVZ, Slackware OpenVZ"; - } elseif (preg_match (":^/people/alien-slaklive/.*:", $_SERVER['REQUEST_URI'])) { - $title = "AlienBOB's Liveslak (Slackware Live Edition)"; - $description = "A Slackware Linux 'live' environment"; - $keywords = "Liveslak, Slackware Live Edition, Slackware Live"; } elseif (preg_match (":^/people/alphageek/.*:", $_SERVER['REQUEST_URI'])) { $title = "Alphageek's SlackBuilds and Packages"; $description = "Alphageek's SlackBuilds and packages (abandoned)"; @@ -92,6 +84,10 @@ $title = "rworkman's SlackBuilds and Packages"; $description = "rworkman's SlackBuilds and packages"; $keywords = "rworkman, rworkman Slackware, rworkman SlackBuild, rworkman SlackBuilds, rworkman packages"; + } elseif ($_SERVER['REQUEST_URI'] == "/people/.*") { + $title = "SlackBuilds and Packages From People"; + $description = "SlackBuilds and packages from individual people"; + $keywords = "Slackware people, alienBOB Slackware, rworkman Slackware, rlworkman Slackware, alphageek Slackware, alienBOB, rworkman, rlworkman, alphageek"; } elseif (preg_match (":^/porteus/.*:", $_SERVER['REQUEST_URI'])) { $title = "Porteus"; $description = "Porteus - Portable Linux"; @@ -108,14 +104,18 @@ $title = "SlackBuilds.org Sources Archive"; $description = "An archive of sources required by SlackBuilds.org packages"; $keywords = "sbosrcarch, SlackBuilds.org, SBo, SlackBuilds source, SlackBuilds sources, SlackBuilds archive"; - } elseif (preg_match (":^/slackar/.*:", $_SERVER['REQUEST_URI'])) { - $title = "Slackware Argentina Project"; - $description = "Slackware Argentina Project"; - $keywords = "Slackware Argentina"; } elseif (preg_match (":^/slackbuilds.org/.*:", $_SERVER['REQUEST_URI'])) { $title = "SlackBuilds.org (SBo)"; $description = "The SlackBuilds.org (SBo) build scripts for Slackware"; $keywords = "SlackBuilds.org, SBo"; + } elseif (preg_match (":^/slackdce/.*:", $_SERVER['REQUEST_URI'])) { + $title = "Slackdce"; + $description = "Slackdce pre-built SBo package repository"; + $keywords = "slackdce, slackbuilds.org, SBo"; + } elseif (preg_match (":^/slackel/.*:", $_SERVER['REQUEST_URI'])) { + $title = "Slackel"; + $description = "Slackel Project"; + $keywords = "Slackel"; } elseif (preg_match (":^/slackintosh/.*:", $_SERVER['REQUEST_URI'])) { $title = "Slackintosh"; $description = "Slackware for Power PC (abandoned)"; @@ -140,6 +140,10 @@ $title = "SlackwareARM"; $description = "Slackware Linux for the ARM platform"; $keywords = "SlackwareARM, ArmedSlack, Slackware ARM, Slackware Linux ARM"; + } elseif (preg_match (":^/slackwareloong/.*:", $_SERVER['REQUEST_URI'])) { + $title = "SlackwareLoong"; + $description = "Slackware for the Loong architecture"; + $keywords = "Slackware Loong"; } elseif (preg_match (":^/slacky/.*:", $_SERVER['REQUEST_URI'])) { $title = "Slacky"; $description = "Slackware packages from the Italian Linux community"; @@ -158,7 +162,7 @@ $keywords = "SlaXBMC, Slackware Xbox"; } elseif (preg_match (":^/slint/.*:", $_SERVER['REQUEST_URI'])) { $title = "Slint Project"; - $description = "The Slint OS, originally derived from Slackware Linux"; + $description = "The Slint OS project"; $keywords = "Slint, Slint OS"; } elseif (preg_match (":^/sls/.*:", $_SERVER['REQUEST_URI'])) { $title = "Softlanding Linux System (SLS)"; @@ -166,7 +170,7 @@ $keywords = "Softlanding Linux System, Softlanding Linux, SLS"; } elseif (preg_match (":^/smlinux/.*:", $_SERVER['REQUEST_URI'])) { $title = "Smlinux"; - $description = "A Slackware-like distribution based on musl-libc"; + $description = "A Slackware-like distribution based on Musl-libc"; $keywords = "Smlinux"; } elseif (preg_match (":^/splack/.*:", $_SERVER['REQUEST_URI'])) { $title = "Splack";
1st September 2025Kelowna
26th August 2025Clear Sky Institute
12th August 2025Bryan Wood
24th July 2025Edward McGuire
6th July 2025Marius Brumback
18th May 2025Daniel Asante
21st April 2025Lluis Tusquellas
18th April 2025Syed Sajjad Rizvi
17th April 2025Henrik Carlqvist
17th April 2025Keith Burnett
17th April 2025Matthew Dinslage
17th April 2025Karl Gunnar Hammarlund
17th April 2025David Ian Allen
17th April 2025Declan Moriarty
10th March 2025Volker Bosch
8th March 2025Timothy S Webster
4th March 2025James FitzRandolph
2nd March 2025Roger Andersson
1st February 2025Jose Luis Gonzalez Becerril
12th January 2025Alain Detal